﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using SpLocalizer.Common.DbApi;
using SpLocalizer.Common.Extensions;

namespace SpLocalizer.Common
{
    public class BaseTranslationTask : ProjectEntity
    {


        protected BaseTranslationTask() { }

        public BaseTranslationTask(CultureInfo FromLanguage, CultureInfo ToLanguage)
        {
            this.FromLanguage = FromLanguage;
            this.ToLanguage = ToLanguage;
        }

        private Guid _TaskId = Guid.NewGuid();
        /// <summary>
        /// Localization task Id
        /// </summary>        
        public virtual Guid TaskId 
        {
            get { return this._TaskId; }
            set { this._TaskId = value; }
        }


        /// <summary>
        /// Source Language (translate from)
        /// </summary>
        public CultureInfo FromLanguage { get; set; }

        /// <summary>
        /// Destination language (translate to)
        /// </summary>
        public CultureInfo ToLanguage { get; set; }

        /// <summary>
        /// Source Text
        /// </summary>
        public String SourceText { get; set; }

        /// <summary>
        /// Translated text
        /// </summary>
        public string TranslatedText { get; set; }

        /// <summary>
        /// Status of translation task
        /// </summary>
        public TranslationTaskStatus Status { get; set; }

        /// <summary>
        /// Return the task provider name
        /// </summary>
        public virtual string TaskProviderName {
            get
            {
                return this.GetType().Name;
            }
        }

        private string _Format = Constants.TASK_FORMAT_TEXT;
        public virtual string Format
        {
            get { return this._Format; }
            set { this._Format = value; }
        }

        /// <summary>
        /// Save task data into database
        /// </summary>
        public virtual void PersistTranslation()
        {
           
            using (SpLocalizerEntities DbEntities = new SpLocalizerEntities())
            {
                TranslationTask TaskToUpdate =
                    DbEntities.TranslationTasks.Where<TranslationTask>(t => t.Id.Equals(this.TaskId)).First<TranslationTask>();
             
               
                TaskToUpdate.Status = (int)this.Status;
             
                TaskToUpdate.NtextValTo = this.TranslatedText;
               

                DbEntities.SaveChanges();

            }
        }


        public static void ResetTranslationTasksQueue()
        {
            using (SpLocalizerEntities DbEntities = new SpLocalizerEntities())
            {
                var q = from tasks in DbEntities.TranslationTasks
                        where tasks.Status == (int)TranslationTaskStatus.WaitForTranslation
                        select tasks;

                foreach (TranslationTask t in q)
                {
                    t.Status = (int)TranslationTaskStatus.Initialized;
                }

                DbEntities.SaveChanges();
            }
        }

        /// <summary>
        /// Initialize task with next database task for translation
        /// </summary>
        /// <param name="task"></param>
        public static BaseTranslationTask LoadFromNextDatabaseTask()
        {
            using (SpLocalizerEntities DbEntities = new SpLocalizerEntities())
            {
                TranslationTask TaskToUpdate = DbEntities.TranslationTasks
                    .Where<TranslationTask>(t => t.Status < (int)TranslationTaskStatus.WaitForTranslation)
                    .FirstOrDefault<TranslationTask>();

                if (TaskToUpdate == null)
                    return null;

                TaskToUpdate.Status = (int)TranslationTaskStatus.WaitForTranslation;
                DbEntities.SaveChanges();
                
                return TaskToUpdate.MakeAbstractTask();

            }
        }

        /// <summary>
        /// Load identical tasks from the database
        /// Identical tasks have the same FromLangoage, ToLanguage and text to translate
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        public List<BaseTranslationTask> LoadIdenticalTasksFromDatabase()
        {
            using (SpLocalizerEntities DbEntities = new SpLocalizerEntities())
            {
                List<TranslationTask> TasksToUpdate = DbEntities.TranslationTasks
                    .Where<TranslationTask>(t => t.Status < (int)TranslationTaskStatus.WaitForTranslation &&
                        t.LcidFrom == this.FromLanguage.LCID && t.LcidTo == this.ToLanguage.LCID
                        && t.NtextValFrom == this.SourceText).ToList<TranslationTask>();

                if (TasksToUpdate.Count > 0)
                {
                    List<BaseTranslationTask> returnValue = new List<BaseTranslationTask>(TasksToUpdate.Count);
                    foreach (TranslationTask t in TasksToUpdate)
                    {
                        returnValue.Add(t.MakeAbstractTask());
                        t.Status = (int)TranslationTaskStatus.WaitForTranslation;
                    }
                    DbEntities.SaveChanges();
                    return returnValue;
                }
                else
                    return null;

            }
        }

        /// <summary>
        /// Trying to find translation in the database
        /// </summary>
        /// <returns></returns>
        public string LookupForTranslations()
        {
            using (SpLocalizerEntities DbEntities = new SpLocalizerEntities())
            {
                TranslationTask translated = DbEntities.TranslationTasks
                    .Where<TranslationTask>(t => t.Status >= (int)TranslationTaskStatus.Translated &&
                        t.LcidFrom == this.FromLanguage.LCID && t.LcidTo == this.ToLanguage.LCID
                        && t.NtextValFrom == this.SourceText && !string.IsNullOrEmpty(t.NtextValTo))
                        .FirstOrDefault<TranslationTask>();

                if (translated != null && !String.IsNullOrEmpty(translated.NtextValTo))
                {
                    return translated.NtextValTo;
                }
                else
                {
                    return null;
                }
            }
        }


    }

    /// <summary>
    /// Status of translation task
    /// </summary>
    public enum TranslationTaskStatus
    
    {
        Empty = 0,
        Initialized = 1,
        WaitForTranslation = 2,
        TranslationInProcess = 3,
        TranslationErrorRetry = 4,
        TranslationErrorFatal = 5,
        /// <summary>
        /// Task sucesfully translated by Translation Provider
        /// </summary>
        Translated = 6,
        ExportError = 8,
        Canceled = 10,
        Exported = 11,
        Compleated = 100
    }
}
